const path = require("path");
const fs = require("fs");
const workDir = path.join(__dirname, "books");
const baseUrl = "https://books-cloud.uniteforliteracy.com/book/";
async function downloadBookById(group, bookId) {
  // 读取input\uniteforliteracy.com\books\stop.txt的内容如果内容字符串true，则程序退出
  if (fs.existsSync(path.join(__dirname, "stop.txt"))) {
    const stop = fs.readFileSync(path.join(__dirname, "stop.txt"), "utf8");
    if (stop === "true") {
      console.log(`  ■获取到停止信号程序停止...`);
      process.exit(0);
    }
  }
  console.log(`Group : ${group}`);
  console.log(` 书籍: ${bookId}`);
  const bookDir = path.join(workDir, group, `${bookId.toString().padStart(4, "0")}`);
  const NullBookDir = `${bookDir}-null`;
  if (fs.existsSync(NullBookDir)) {
    console.log(`  书籍已存在，跳过...`);
    return;
  }
  let bookInfo = null;
  const bookInfoFile = path.join(bookDir, "bookInfo.json");
  if (fs.existsSync(bookInfoFile)) {
    console.log(`  书籍信息已存在，从bookInfo.json文件中获取...`);
    bookInfo = JSON.parse(fs.readFileSync(bookInfoFile));
  } else {
    const bookInfoUrl = `${baseUrl}${bookId}/book1.json?v=p5116587241`;
    // fetch请求，获取返回结果json
    console.log(`  正在获取书籍信息...: ${bookInfoUrl}`);
    const bookInfoResponse = await fetch(bookInfoUrl, {
      headers: {
        accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
        "accept-language": "en-GB,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,en-US;q=0.6",
        "cache-control": "no-cache",
        pragma: "no-cache",
        priority: "u=0, i",
        "sec-ch-ua": '"Not;A=Brand";v="99", "Microsoft Edge";v="139", "Chromium";v="139"',
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": '"Windows"',
        "sec-fetch-dest": "document",
        "sec-fetch-mode": "navigate",
        "sec-fetch-site": "none",
        "sec-fetch-user": "?1",
        "upgrade-insecure-requests": "1",
      },
      body: null,
      method: "GET",
      mode: "cors",
      credentials: "include",
    });
    // 如果bookInfo是JSON字符串，则继续，否则直接返回
    if (bookInfoResponse.status !== 200) {
      // 创建Null目录
      fs.mkdirSync(NullBookDir, { recursive: true });
      console.log(`  获取书籍信息失败: ${bookInfoResponse.status}`);
      return;
    } else {
      // 如果存在bookDir，且内容不为空，则直接返回
      if (!fs.existsSync(bookDir)) {
        fs.mkdirSync(bookDir, { recursive: true });
      }
    }

    // 解析响应中的JSON数据
    bookInfo = await bookInfoResponse.json();
    fs.writeFileSync(bookInfoFile, JSON.stringify(bookInfo, null, 2));
  }
  console.log(`  书籍信息获取成功...`);

  if (bookInfo.Abbv !== "eng") {
    console.log(`  书籍不是英文，跳过...`);
    // 清理目录下除了bookInfo.json的全部文件夹及文件
    fs.readdirSync(bookDir).forEach(file => {
      if (file !== "bookInfo.json") {
        fs.rmSync(path.join(bookDir, file), { recursive: true, force: true });
      }
    });
    return;
  }
  // 获取bookInfo中的bookID
  const bookTitle = bookInfo.Title;
  if (!bookTitle) {
    console.log(`  书籍标题为空....`);
    return;
  }
  console.log(`  书籍标题: ${bookTitle}`);
  fs.mkdirSync(bookDir, { recursive: true });
  // 将${bookTitle}写入到pageDir下的title.txt文件中
  fs.writeFileSync(path.join(bookDir, "title.txt"), bookTitle);
  const bookPages = bookInfo.Pages;
  for (let i = 0; i < bookPages.length; i++) {
    const pageDir = path.join(bookDir, i.toString());
    fs.mkdirSync(pageDir, { recursive: true });
    const bookPage = bookPages[i];
    const bookPageImageUrl = bookPage.ImageUrl;
    if (bookPageImageUrl && bookPageImageUrl !== "") {
      const imageUrl = `https://files-cloud.uniteforliteracy.com/book/${bookId}/picset/th480/${bookPageImageUrl}?v=p500`;
      await downloadFile(imageUrl, path.join(pageDir, "image.jpg"));
    }

    const bookPageMp3 = bookPage.mp3;
    if (bookPageMp3 && bookPageMp3 !== "") {
      const mp3Url = `https://files-cloud.uniteforliteracy.com/book/${bookId}/eng/audio/eng/${bookPageMp3}?v=p500`;
      await downloadFile(mp3Url, path.join(pageDir, "audio.mp3"));
    }

    const bookPagePageText = bookPage.PageText;
    if (bookPagePageText && bookPagePageText !== "") {
      // 将text去掉dom标签后，写入到pageDir下的text.txt文件中
      const htmlText = bookPagePageText.replace(/<[^>]+>/g, "");
      fs.writeFileSync(path.join(pageDir, "text.txt"), htmlText);
    }
  }
}
/**
 * download resource from url and save to output
 * @param {String} url Resource URL
 * @param {String} output Output file path
 */
async function downloadFile(url, output) {
  // 如果目标文件存在，且大小大于0，则跳过
  if (fs.existsSync(output) && fs.statSync(output).size > 0) {
    console.log(` -> Skipped ${url}`);
    return;
  }
  const response = await fetch(url);
  const buffer = await response.arrayBuffer();
  fs.writeFileSync(output, Buffer.from(buffer));
  console.log(`    Downloaded ${url}`);
  console.log(`    --> to ${output}`);
}
/**
 * download book group
 */
async function downLoadBookGroup() {
  // 从
  // https://reader-cloud.uniteforliteracy.com/lib/r16/libInfoCombo.json?v=p5133617241
  // 获取groups
  let groups = [];
  if (fs.existsSync(path.join(workDir, "groups.json"))) {
    groups = JSON.parse(fs.readFileSync(path.join(workDir, "groups.json")));
  } else {
    const groupsUrl = "https://reader-cloud.uniteforliteracy.com/lib/r16/libInfoCombo.json?v=p5133617241";
    const groupsResponse = await fetch(groupsUrl);
    groups = await groupsResponse.json();
    fs.writeFileSync(path.join(workDir, "groups.json"), JSON.stringify(groups, null, 2));
  }
  // 遍历groups,获取groups中的Books
  for (let groupID in groups) {
    const group = groups[groupID];
    const groupTitle = group.Title;

    if (group.WLangAbbv !== "eng") {
      console.log(`  书籍【组】不是英文，跳过...`);
      // 如果存在path.join(workDir, groupTitle)文件夹，则清理文件夹
      if (fs.existsSync(path.join(workDir, groupTitle))) {
        fs.rmSync(path.join(workDir, groupTitle), { recursive: true, force: true });
      }
      continue;
    }
    fs.mkdirSync(path.join(workDir, groupTitle), { recursive: true });
    const books = group.Books;
    // 遍历books,获取books中的BookID
    for (const book of books) {
      const bookID = book.BKID;
      await downloadBookById(groupTitle, bookID);
    }
  }
}

async function main() {
  await downLoadBookGroup();
}

main();
